﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Security.Cryptography;
using System.Text;
using System.Globalization;

namespace Infrastructure.Utility
{
    public class Security
    {
        private char[] key = new char[0x80];
        private int m;
        private char[] pass;
        public const int PasswordLength = 8;
        private char[] r = new char[0x80];
        private const int USERCODEMASTLEN = 0x80;
        private const string INTERFERE_KEY = "%";
        private int Association(int size)
        {
            return ((size + this.m) % 0x3e5);
        }

        private static byte[] CharArray2ByteArray(int len, Security encryption)
        {
            byte[] buffer = new byte[len];
            for (int i = 0; i < len; i++)
            {
                buffer[i] = Convert.ToByte(encryption.pass[i]);
            }
            return buffer;
        }

        private static int CharArrayLength(char[] a)
        {
            int num = 0;
            for (int i = 0; i < 0x80; i++)
            {
                if (a[i] != '\0')
                {
                    num++;
                }
                else
                {
                    return num;
                }
            }
            return num;
        }

        public static string EncodeString(string buffer, int len, string key)
        {
            if (buffer == null)
            {
                throw new Exception("传入密钥为空");
            }
            if (string.IsNullOrEmpty(key))
            {
                key = string.Empty;
            }
            char[] array = new char[0x400];
            char[] chArray2 = new char[80];
            Security encryption = new Security();
            buffer.ToCharArray().CopyTo(array, 0);
            key.ToCharArray().CopyTo(chArray2, 0);
            encryption.Secret(array, len, chArray2);
            return Convert.ToBase64String(CharArray2ByteArray(len, encryption));
        }

        public static byte[] EncodeString2ByteArray(string buffer, int len, string key)
        {
            if (buffer == null)
            {
                throw new Exception("传入密钥为空");
            }
            if (string.IsNullOrEmpty(key))
            {
                key = string.Empty;
            }
            char[] array = new char[0x400];
            char[] chArray2 = new char[80];
            Security encryption = new Security();
            buffer.ToCharArray().CopyTo(array, 0);
            key.ToCharArray().CopyTo(chArray2, 0);
            encryption.Secret(array, len, chArray2);
            return CharArray2ByteArray(len, encryption);
        }

        public static string EncodeStringSql(string buffer, int len, string key)
        {
            if (buffer == null)
            {
                throw new Exception("传入密钥为空");
            }
            if (string.IsNullOrEmpty(key))
            {
                key = string.Empty;
            }
            char[] array = new char[0x400];
            char[] chArray2 = new char[80];
            string str = "";
            Security encryption = new Security();
            buffer.ToCharArray().CopyTo(array, 0);
            key.ToCharArray().CopyTo(chArray2, 0);
            encryption.Secret(array, len, chArray2);
            char[] chArray3 = encryption.EncryptPassword.ToCharArray();
            str = "char(" + Convert.ToByte(chArray3[0]).ToString() + ")";
            for (int i = 1; i < len; i++)
            {
                str = str + "+char(" + Convert.ToByte(chArray3[i]).ToString() + ")";
            }
            return (str + "+char(0)");
        }

        private void Exchange(char[] buf, int size, int associat)
        {
            int num = (Convert.ToByte(this.key[this.m - 1]) + (0x80 % (0x80 - this.m))) % 0xff;
            int index = 0;
            for (int i = 0; i <= (size - 1); i++)
            {
                int num4 = (((this.key[index] + num) + i) + index) % 2;
                int num5 = ((((this.key[index] + num) + i) + index) + associat) % this.m;
                this.key[index] = Convert.ToChar((int)(this.key[index] ^ (this.key[num5] >> 1)));
                num5 = ((((num5 + num4) + i) + associat) % 6) + 1;
                if (num4 == 0)
                {
                    this.key[index] = Convert.ToChar((int)(((this.key[index] << (num5 & 0x1f)) & '\x00ff') ^ (num ^ this.key[num5])));
                }
                else
                {
                    this.key[index] = Convert.ToChar((int)((this.key[index] >> (num5 & 0x1f)) ^ (~(num ^ this.key[num5]) & 0xff)));
                }
                num = this.key[index];
                buf.GetUpperBound(0);
                buf[i] = Convert.ToChar((int)(buf[i] ^ num));
                if (index < this.m)
                {
                    index++;
                }
                else
                {
                    index = 0;
                }
            }
        }

        private void FirstKey(char[] buf)
        {
            int index = 0;
            while (index <= 0x7f)
            {
                this.r[index] = '\0';
                this.key[index] = '\0';
                index++;
            }
            buf.CopyTo(this.key, 0);
            int num2 = CharArrayLength(this.key);
            this.key[num2] = '\x00fc';
            this.m = CharArrayLength(this.key);
            while (this.m < 0x40)
            {
                this.m = CharArrayLength(this.key);
                for (index = 0; index <= (this.m - 1); index++)
                {
                    this.key[this.m + index] = this.key[index];
                }
                this.m = CharArrayLength(this.key);
            }
            this.m = CharArrayLength(this.key);
            this.PreProcess();
        }

        private void LoadKey()
        {
            for (int i = 0; i <= (this.m - 1); i++)
            {
                this.key[i] = this.r[i];
            }
        }

        private void PreProcess()
        {
            for (int i = 0; i <= 0xfe; i++)
            {
                for (int j = 0; j <= (this.m - 1); j++)
                {
                    int num3 = Convert.ToByte(this.key[j]) & 0xff;
                    this.r[j] = Convert.ToChar((int)((num3 >> 4) + ((num3 & 15) << 4)));
                    this.key[j] = this.r[j];
                }
                this.Exchange(this.r, this.m, this.m);
            }
        }

        private void Secret(char[] buffer, int len, char[] passkey)
        {
            this.FirstKey(passkey);
            int associat = this.Association(len);
            this.LoadKey();
            this.pass = new char[buffer.Length];
            buffer.CopyTo(this.pass, 0);
            this.Exchange(this.pass, len, associat);
        }

        public string EncryptPassword
        {
            get
            {
                return new string(this.pass);
            }
        }

        public string UNEncryptPassword
        {
            get
            {
                string str = new string(this.pass);
                string str2 = "";
                for (int i = 0; i < str.Length; i++)
                {
                    if (str[i] != '\0')
                    {
                        str2 = str2 + str[i];
                    }
                    else
                    {
                        return str2;
                    }
                }
                return str2;
            }
        }

        // 加密字符串
        public static string EncryptString(string content, string key, int length = 0)
        {
            byte[] data = Encoding.UTF8.GetBytes(content);
            string ekey = INTERFERE_KEY + key + "       ";
            byte[] byteKey = new byte[8];
            Array.ConstrainedCopy(ASCIIEncoding.ASCII.GetBytes(ekey), 0, byteKey, 0, byteKey.Length);
            byte[] byteIV = new byte[8];
            Array.ConstrainedCopy(ASCIIEncoding.ASCII.GetBytes(ekey), 0, byteIV, 0, byteIV.Length);
            DESCryptoServiceProvider DES = new DESCryptoServiceProvider { Key = byteKey, IV = byteIV };
            ICryptoTransform desencrypt = DES.CreateEncryptor();
            byte[] result = desencrypt.TransformFinalBlock(data, 0, data.Length);
            var encode = BitConverter.ToString(result).Replace("-", string.Empty);
            if (length > 0 && length < encode.Length) return encode.Substring(0, length);
            else return encode;
            
        }
    }
}
